from datetime import datetime
from flask import json, request, session
from exts import db
from werkzeug.security import generate_password_hash, check_password_hash
from sqlalchemy import func
from models.user import AdminUser, RoleType

from services.user_service import *

from datetime import datetime, timedelta, timezone
import jwt
from flask import current_app
from functools import wraps


class auth_service:
    def generate_token(self, user):
        payload = {
            "user_id": user.id,
            "username": user.username,
            "exp": datetime.now(timezone.utc) + timedelta(hours=current_app.config["JWT_ACCESS_TOKEN_EXPIRES"]),
        }
        return jwt.encode(payload, current_app.config["SECRET_KEY"], algorithm="HS256")

    # 验证token 装饰器
    def verify_token(self, f):
        @wraps(f)
        def decorated(*args, **kwargs):
            token = request.headers.get("token", None)
            if not token:
                return {"message": "Token缺失"}, 401  # 修改为返回JSON响应
            
            try:
                payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
                user_id = payload.get("user_id")
                if not user_id:
                    return {"message": "无效Token"}, 401  # 修改为返回JSON响应
            except jwt.ExpiredSignatureError:
                return {"message": "Token已过期"}, 401  # 修改为返回JSON响应
            except jwt.InvalidTokenError:
                return {"message": "无效Token"}, 401  # 修改为返回JSON响应
            except Exception as e:
                return {"message": str(e)}, 400  # 修改为返回JSON响应

            return f(*args, **kwargs)

        return decorated
    
    # 从token中获取role_type信息并比对，验证权限是否足够
    def get_role_type(self, token, role_type):
        try:
            payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
            user_role_type = user_service.get_user_info(payload.get("user_id")).role_type
            if payload.get("role_type") == user_role_type and payload.get("role_type") == role_type:
                return role_type
            else:
                raise Exception("权限不足")
        except Exception as e:
            return None

    def login(self, post_json):
        username = post_json.get("username")
        password = post_json.get("password")
        if not username or not password:
            raise Exception("参数错误")
        user = AdminUser.query.filter_by(username=username).first()
        if not user:
            raise Exception("用户名或密码错误")
        if not check_password_hash(user.password_hash, password):
            raise Exception("用户名或密码错误")
        # 生成JWT Token
        token = self.generate_token(user)
        return {
            "token": token,
            "user_info":user_service().get_user_info(user.id),
        }
    
    

    # 新增带参数的装饰器方法
    def require_role(self, required_roles):
        # 若传入单个角色，将其转换为列表
        if not isinstance(required_roles, list):
            required_roles = [required_roles]

        def decorator(f):
            @wraps(f)
            def decorated(*args, **kwargs):
                try:
                    token = request.headers.get("token")
                    if not token:
                        return {"message": "Token缺失"}, 401
                    
                    try:
                        payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
                        user_id = payload.get("user_id")
                        if not user_id:
                            return {"message": "无效Token"}, 401
                            
                        # 获取用户实际角色 - 修改为实例化调用
                        user = user_service().get_user_info(user_id)  # 注意这里加了括号实例化
                        user_role = RoleType(user["role_type"])
                        
                        # 超级管理员拥有所有权限
                        if user_role == RoleType.SUPER:
                            return f(*args, **kwargs)
                            
                        # 检查用户角色是否匹配要求的角色列表中的任意一个
                        if user_role not in required_roles:
                            return {"message": "权限不足"}, 403
                            
                    except jwt.ExpiredSignatureError:
                        return {"message": "Token已过期"}, 401
                    except jwt.InvalidTokenError:
                        return {"message": "无效Token"}, 401
                    except ValueError as e:
                        return {"message": f"无效的角色类型: {str(e)}"}, 400
                        
                    return f(*args, **kwargs)
                    
                except Exception as e:
                    return {"message": f"服务器错误: {str(e)}"}, 500
                    
            return decorated
        return decorator

    def get_user_id_from_token(self):
        """从请求头中的token获取用户ID"""
        token = request.headers.get("token")
        if not token:
            raise Exception("Token缺失")
        try:
            payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
            return payload.get("user_id")
        except jwt.ExpiredSignatureError:
            raise Exception("Token已过期")
        except jwt.InvalidTokenError:
            raise Exception("无效Token")

    def get_username_from_token(self):
        """从请求头中的token获取用户名"""
        token = request.headers.get("token")
        if not token:
            raise Exception("Token缺失")
        try:
            payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
            return payload.get("username")
        except jwt.ExpiredSignatureError:
            raise Exception("Token已过期")
        except jwt.InvalidTokenError:
            raise Exception("无效Token")

    def get_user_info_from_token(self):
        """从请求头中的token获取完整用户信息"""
        token = request.headers.get("token")
        if not token:
            raise Exception("Token缺失")
        try:
            payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
            user_id = payload.get("user_id")
            if not user_id:
                raise Exception("无效Token")
            return user_service().get_user_info(user_id)
        except jwt.ExpiredSignatureError:
            raise Exception("Token已过期")
        except jwt.InvalidTokenError:
            raise Exception("无效Token")

    def logout(self):
        """退出登录"""
        try:
            return {
                "message": "退出登录成功",
            }
        except Exception as e:
            return {"message": f"退出登录失败: {str(e)}"}, 500